package com.chen.common.swagger.config;

import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.*;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.schema.ScalarType;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 网址 -> http://网关IP:网关端口/doc.html
 * @author Long
 */
@Slf4j
@Configuration
@EnableOpenApi
public class SwaggerServerConfig {

    @Value("${server.port:8080}")
    private String port;
    @Value("${spring.application.name}")
    private String serverName;
    @Value("${enable.swagger:true}")
    private boolean enableSwagger;
    @Value("${server.servlet.context-path:}")
    private String contextPath;

    @PostConstruct
    public void init(){
        if (enableSwagger){
            log.info("接口文档:  http://{}:{}{}/doc.html", NetUtil.getLocalhostStr(), port, contextPath);
        }
    }

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.OAS_30)
                .enable(enableSwagger)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com"))
                .paths(PathSelectors.any())
                .build()
                .globalRequestParameters(globalRequestParameters())
                .apiInfo(apiInfo())
                .securitySchemes(Collections.singletonList(securityScheme()))
                .securityContexts(Collections.singletonList(securityContext()));
    }

    private List<RequestParameter> globalRequestParameters() {
        RequestParameterBuilder parameterBuilder = new RequestParameterBuilder()
                .in(ParameterType.HEADER)
                .name("Authorization")
                .required(true)
                .description("Bearer token")
                .query(param -> param.model(model -> model.scalarModel(ScalarType.STRING)));
        return Collections.singletonList(parameterBuilder.build());
    }
    
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title(serverName + "服务API")
                .description(serverName + "接口文档管理")
                .termsOfServiceUrl(StrUtil.format("http://{}:{}/", NetUtil.getLocalhostStr(),port))
                .version("1.0.0")
                .build();
    }

    /**
     * 用于配置安全策略，比如配置认证模型，scope等内容
     */
    private SecurityScheme securityScheme() {
        GrantType grantType = new ResourceOwnerPasswordCredentialsGrant("http://localhost:8081/auth/oauth/token");
        return new OAuthBuilder()
                .name("Authorization")
                .grantTypes(Collections.singletonList(grantType))
                .scopes(Arrays.asList(scopes()))
                .build();
    }

    /**
     * 这里设置 swagger2 认证的安全上下文
     */
    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(Collections.singletonList(new SecurityReference("Authorization", scopes())))
                .forPaths(PathSelectors.any())
                .build();
    }

    /**
     * 这里是写允许认证的scope
     */
    private AuthorizationScope[] scopes() {
        return new AuthorizationScope[]{new AuthorizationScope("all", "")};
    }
}
